// (C) 2022 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

`timescale 1 ps / 1 ps
`default_nettype none

module pfr_core (
    // Clocks and resets
    input wire clk2M,
    input wire clk50M,
    input wire sys_clk,
    input wire spi_clk,
    input wire clk100M,
    input wire clk2M_reset_sync_n,
    input wire clk50M_reset_sync_n,
    input wire sys_clk_reset_sync_n,
    input wire spi_clk_reset_sync_n,
    input wire clk100M_reset_sync_n,
    
    // BMC and CPU resets from common core
    input wire PWRGD_AUX_PWRGD_CPU0,
    input wire PWRGD_AUX_PWRGD_CPU1,
    input wire RST_SRST_BMC_PFR_N,
    
    // HPFR Signals
    input wire FM_HPFR_IN,
    output wire FM_HPFR_OUT,
    input wire FM_HPFR_LEGACY,
    input wire FM_HPFR_ACTIVE, 
    
    input wire FM_PFR_FORCE_RECOVERY_N,
    output wire FM_PFR_BMC_SPI_MASTERSEL,
    output wire FM_PFR_CPU0_SPI_MASTERSEL,

    input wire FP_ID_LED_BMC_N,
    output wire FP_ID_LED_N,
    input wire FP_LED_STATUS_AMBER_BMC_N,
    output wire FP_LED_STATUS_AMBER_N,
    input wire FP_LED_STATUS_GREEN_BMC_N,
    output wire FP_LED_STATUS_GREEN_N,
    output wire RST_PFR_BMC_EXTRST_N,
    output wire PFR_CPU0_RTC_RST_N,
    output wire PFR_CPU1_RTC_RST_N,
    output wire RST_PFR_BMC_SPI_RESET_N,
    output wire RST_SPI_PFR_CPU0_RESET_N,
    inout wire SMB_HSBP_BMC_SCL_LVC3,
    inout wire SMB_HSBP_BMC_SDA_LVC3,
    inout wire SMB_PMBUS2_BMC_LVC3_SCL,
    inout wire SMB_PMBUS2_BMC_LVC3_SDA,
    inout wire SMB_HSBP_SCM_SCL_LVC3_R1,
    inout wire SMB_HSBP_SCM_SDA_LVC3_R1,
    inout wire SMB_PMBUS1_SCM_SCL_R,
    inout wire SMB_PMBUS1_SCM_SDA_R,
    inout wire SMB_PMBUS2_SCM_SCL_R,
    inout wire SMB_PMBUS2_SCM_SDA_R,
    inout wire SMB_PCIE_PFR_SCL_LVC3_R1,
    inout wire SMB_PCIE_PFR_SDA_LVC3_R1,
    output wire SMB_PFR_RFID_SCL,
    inout wire SMB_PFR_RFID_SDA,
    inout wire SMB_PMBUS1_BMC_LVC3_SCL,
    inout wire SMB_PMBUS1_BMC_LVC3_SDA,

    input wire SPI_BMC_PFR_MON_CS0_N,
    input wire SPI_BMC_PFR_MON_CLK,
    input wire SPI_BMC_PFR_MON_IO1,
    input wire SPI_BMC_PFR_MON_IO0,
    input wire SPI_BMC_PFR_MON_IO2,
    input wire SPI_BMC_PFR_MON_IO3,
    input wire SPI_CPU0_PFR_MON_CLK,
    inout wire SPI_CPU0_PFR_MON_IO0,
    inout wire SPI_CPU0_PFR_MON_IO1,
    inout wire SPI_CPU0_PFR_MON_IO2,
    inout wire SPI_CPU0_PFR_MON_IO3,
    input wire SPI_CPU0_PFR_MON_CS0_SWAP_N,
    input wire SPI_CPU0_PFR_MON_CS1_SWAP_N,
    output wire SPI_OPFR_CPU0_CS0_LVC18_N,
    inout wire SPI_OPFR_BMC_IO2_LVC3_R,
    inout wire SPI_OPFR_BMC_IO3_LVC3_R,
    output wire SPI_OPFR_BMC_CS0_LVC3_N,
    output wire SPI_CLK_OPFR_BMC_LVC3,
    inout wire SPI_OPFR_BMC_IO1_LVC3_R,
    inout wire SPI_OPFR_BMC_IO0_LVC3_R,
    output wire SPI_CLK_OPFR_CPU0_LVC18,
    inout wire SPI_OPFR_CPU0_IO0_LVC18_R,
    inout wire SPI_OPFR_CPU0_IO1_LVC18_R,
    inout wire SPI_OPFR_CPU0_IO2_LVC18_R,
    inout wire SPI_OPFR_CPU0_IO3_LVC18_R,
    input wire RST_PLTRST_CPU0_N,
    input wire RST_PLTRST_CPU1_N,
    output wire RST_SRST_BMC_SCM_FPGA_N,
    output wire PWRGD_AUX_PWRGD_PFR_CPU0,
    output wire PWRGD_AUX_PWRGD_PFR_CPU1,
    output wire SPI_OPFR_CPU0_CS1_LVC18_N,
    
    // I2C interface for online CPLD update
    inout wire	SMB_CPLD_UPDATE_PFR_SCL_LVC3_R,
    inout wire	SMB_CPLD_UPDATE_PFR_SDA_LVC3_R,

    output wire	RST_SPI_PFR_CPU1_N,
    output wire	SPI_CPU1_PFR_CTRL_CS_N,
	output wire	SPI_CPU1_PFR_CTRL_CS1_N,
    input wire	SPI_CPU1_PFR_MON_CS0_N,
	input wire	SPI_CPU1_PFR_MON_CS1_N,
    output wire	FM_PFR_CPU1_SPI_MASTERSEL,
    inout wire	SPI_CPU1_PFR_CTRL_CLK,
    inout wire	SPI_CPU1_PFR_CTRL_MOSI,
    inout wire	SPI_CPU1_PFR_CTRL_MISO,
    inout wire	SPI_CPU1_PFR_CTRL_IO2,
    inout wire	SPI_CPU1_PFR_CTRL_IO3,
    input wire	SPI_CPU1_PFR_MON_CLK,
    inout wire	SPI_CPU1_PFR_MON_IO0,
    inout wire	SPI_CPU1_PFR_MON_IO1,
    inout wire	SPI_CPU1_PFR_MON_IO2,
    inout wire	SPI_CPU1_PFR_MON_IO3,
    
    output wire	SPI_PFR_CS0_N,
    inout wire  SPI_PFR_CLK,
    inout wire  SPI_PFR_IO0,
    inout wire  SPI_PFR_IO1,
    inout wire  SPI_PFR_IO2,
    inout wire  SPI_PFR_IO3,
    output wire	RST_SPI_PFR_RESET_N,
    
    inout wire	I3C_PFR_BMC_SCL,
    inout wire	I3C_PFR_BMC_SDA,
    output wire	FM_I3C_PFR_BMC_PUR_EN,
    inout wire	I3C_PFR_PCIE_SCL,
    inout wire	I3C_PFR_PCIE_SDA,
    output wire	FM_I3C_PFR_PCIE_PUR_EN,
    inout wire	I3C_PFR_MNG_SCL,
    inout wire  I3C_PFR_MNG_SDA,
    output wire	FM_I3C_PFR_MNG_PUR_EN,
    
    output wire	RST_PLTRST_CPU0_PFR_LVC3_N,
    output wire	RST_PLTRST_CPU1_PFR_LVC3_N,
    
    input wire	FP_BMC_PWR_BTN_N,
    output wire	FP_PWR_BTN_PFR_N,
    input wire	FM_PFR_DEBUG_JUMPER,
    
    output wire	SGPIO_PFR_DOUT,
    output wire	SGPIO_PFR_CLK,
    input wire	SGPIO_PFR_DIN,
    output wire	SGPIO_PFR_LD_N,
    input wire	FM_PFR_CC_RSVD_0,
    input wire	FM_PFR_CC_RSVD_1,
    output wire	FM_PFR_CC_RSVD_2,
    output wire	FM_PFR_CC_RSVD_3,
    output wire	FM_PFR_CC_RSVD_4,
    
    output wire FM_PFR_MNG_SEL,
    output wire FM_PFR_PCIE_SEL,
	 
	output wire FM_PFR_SMB_CPLD_UPDATE_SEL,
	
	input wire tdi_external,
	input wire tck_external,
	input wire tms_external,
	output wire tdo_external

);

    // Import the GPI names
    import gen_gpi_signals_pkg::*;

    //Import the platform defs names
    import platform_defs_pkg::*;
    
    // general purpose outputs
    wire [31:0] gpo_1;
    wire [31:0] gpo_2;
    
    // general purpose inputs
    wire [31:0] gpi_1;

    // global state broadcast
    wire [31:0] global_state;

    // SBus Mailbox AVMM interface
    wire        mailbox_avmm_clk;
    wire        mailbox_avmm_areset;
    wire [7:0]  mailbox_avmm_address;
    wire        mailbox_avmm_waitrequest;
    wire        mailbox_avmm_read;
    wire        mailbox_avmm_write;
    wire [31:0] mailbox_avmm_readdata;
    wire [31:0] mailbox_avmm_writedata;
    wire        mailbox_avmm_readdatavalid;

    // RFNVRAM master AVMM interface
    wire        rfnvram_avmm_clk;
    wire        rfnvram_avmm_areset;
    wire [3:0]  rfnvram_avmm_address;
    wire        rfnvram_avmm_waitrequest;
    wire        rfnvram_avmm_read;
    wire        rfnvram_avmm_write;
    wire [31:0] rfnvram_avmm_readdata;
    wire [31:0] rfnvram_avmm_writedata;
    wire        rfnvram_avmm_readdatavalid;
    
    // SMBUS relay AVMM interfaces
    wire [7:0]  relay1_avmm_address;
    wire        relay1_avmm_write;
    wire [31:0] relay1_avmm_writedata;
    wire [7:0]  relay2_avmm_address;
    wire        relay2_avmm_write;
    wire [31:0] relay2_avmm_writedata;
    wire [7:0]  relay3_avmm_address;
    wire        relay3_avmm_write;
    wire [31:0] relay3_avmm_writedata;

    // Timer bank AVMM interface
    wire        timer_bank_avmm_clk;
    wire        timer_bank_avmm_areset;
    wire [2:0]  timer_bank_avmm_address;
    wire        timer_bank_avmm_waitrequest;
    wire        timer_bank_avmm_read;
    wire        timer_bank_avmm_write;
    wire [31:0] timer_bank_avmm_readdata;
    wire [31:0] timer_bank_avmm_writedata;

    // Crypto block AVMM interface
    wire        crypto_avmm_clk;
    wire        crypto_avmm_areset;
    wire [6:0]  crypto_avmm_address;
    wire        crypto_avmm_read;
    wire        crypto_avmm_write;
    wire [31:0] crypto_avmm_readdata;
    wire        crypto_avmm_readdatavalid;
    wire [31:0] crypto_avmm_writedata;

    // SPI Master CSR AVMM interface
    wire [5:0]  spi_master_csr_avmm_address;
    wire        spi_master_csr_avmm_waitrequest;
    wire        spi_master_csr_avmm_read;
    wire        spi_master_csr_avmm_write;
    wire [31:0] spi_master_csr_avmm_readdata;
    wire        spi_master_csr_avmm_readdatavalid;
    wire [31:0] spi_master_csr_avmm_writedata;

    // SPI Master AVMM interface to SPI memory
    wire [24:0] spi_master_avmm_address;
    wire        spi_master_avmm_waitrequest;
    wire        spi_master_avmm_read;
    wire        spi_master_avmm_write;
    wire [31:0] spi_master_avmm_readdata;
    wire [31:0] spi_master_avmm_writedata;
    wire        spi_master_avmm_readdatavalid;

    // SPI Filter AVMM interface to BMC and SPI filters to control which sections of each FLASH device suppor write/erase commands (to be configured based on the PFM)
    wire        spi_filter_bmc_we_avmm_clk;
    wire        spi_filter_bmc_we_avmm_areset;
    wire [13:0] spi_filter_bmc_we_avmm_address;     // address window is larger than actually required, some top address bits will be ignored
    wire        spi_filter_bmc_we_avmm_write;
    wire [31:0] spi_filter_bmc_we_avmm_writedata;
    wire        spi_filter_bmc_we_avmm_read;
    wire [31:0] spi_filter_bmc_we_avmm_readdata;
    wire        spi_filter_bmc_we_avmm_readdatavalid;
    wire [13:0] spi_filter_cpu0_flash0_we_avmm_address;     // address window is larger than actually required, some top address bits will be ignored
    wire        spi_filter_cpu0_flash0_we_avmm_write;
    wire [31:0] spi_filter_cpu0_flash0_we_avmm_writedata;
    wire        spi_filter_cpu0_flash0_we_avmm_read;
    wire [31:0] spi_filter_cpu0_flash0_we_avmm_readdata;
    wire        spi_filter_cpu0_flash0_we_avmm_readdatavalid;
	wire [13:0] spi_filter_cpu0_flash1_we_avmm_address;     // address window is larger than actually required, some top address bits will be ignored
    wire        spi_filter_cpu0_flash1_we_avmm_write;
    wire [31:0] spi_filter_cpu0_flash1_we_avmm_writedata;
    wire        spi_filter_cpu0_flash1_we_avmm_read;
    wire [31:0] spi_filter_cpu0_flash1_we_avmm_readdata;
    wire        spi_filter_cpu0_flash1_we_avmm_readdatavalid;
    wire [13:0] spi_filter_cpu1_flash0_we_avmm_address;     // address window is larger than actually required, some top address bits will be ignored
    wire        spi_filter_cpu1_flash0_we_avmm_write;
    wire [31:0] spi_filter_cpu1_flash0_we_avmm_writedata;
    wire        spi_filter_cpu1_flash0_we_avmm_read;
    wire [31:0] spi_filter_cpu1_flash0_we_avmm_readdata;
    wire        spi_filter_cpu1_flash0_we_avmm_readdatavalid;
	wire [13:0] spi_filter_cpu1_flash1_we_avmm_address;     // address window is larger than actually required, some top address bits will be ignored
    wire        spi_filter_cpu1_flash1_we_avmm_write;
    wire [31:0] spi_filter_cpu1_flash1_we_avmm_writedata;
    wire        spi_filter_cpu1_flash1_we_avmm_read;
    wire [31:0] spi_filter_cpu1_flash1_we_avmm_readdata;
    wire        spi_filter_cpu1_flash1_we_avmm_readdatavalid;
	 
    // Crypto DMA AVMM interface to Crypto DMA's CSR
    logic           crypto_dma_avmm_clk;
    logic           crypto_dma_avmm_areset;
    logic [1:0]     crypto_dma_avmm_address;
    logic           crypto_dma_avmm_read;
    logic           crypto_dma_avmm_write;
    logic [31:0]    crypto_dma_avmm_readdata;
    logic [31:0]    crypto_dma_avmm_writedata;
    
    // I3C AVMM interface to I3C host
    logic           i3c_avmm_clk;
    logic           i3c_avmm_areset;
    logic           i3c_avmm_read;
    logic [31:0]    i3c_avmm_readdata;
    logic           i3c_avmm_readdatavalid;
    logic           i3c_avmm_write;
    logic [31:0]    i3c_avmm_writedata;
    logic [7:0]     i3c_avmm_address;
    logic           i3c_avmm_waitrequest;
	 
    //I3C PLL generated i3c_core_clk interface
    logic           i3c_core_clk;
    logic           i3c_core_reset_n;
    
    logic        aes256_gcm_avmm_clk;        
    logic        aes256_gcm_avmm_areset;     
    logic [7:0]  aes256_gcm_avmm_address;    
    logic        aes256_gcm_avmm_waitrequest;
    logic        aes256_gcm_avmm_read;       
    logic        aes256_gcm_avmm_readdatavalid;       
    logic        aes256_gcm_avmm_write;      
    logic [31:0] aes256_gcm_avmm_readdata;   
    logic [31:0] aes256_gcm_avmm_writedata;  
    // signals for logging blocked SPI commands
    logic [31:0]                         bmc_spi_filtered_command_info; // 31:14 - address bits 31:14 of filtered command, 13 - 1=illegal command, 0=illegal write/erase region, 12:8- number of filtered commands, 7:0 - command that was filtered
    logic [31:0]                         cpu0_flash0_spi_filtered_command_info; // 31:14 - address bits 31:14 of filtered command, 13 - 1=illegal command, 0=illegal write/erase region, 12:8- number of filtered commands, 7:0 - command that was filtered
	logic [31:0]                         cpu0_flash1_spi_filtered_command_info; // 31:14 - address bits 31:14 of filtered command, 13 - 1=illegal command, 0=illegal write/erase region, 12:8- number of filtered commands, 7:0 - command that was filtered
    logic [31:0]                         cpu1_spi_filtered_command_info; // 31:14 - address bits 31:14 of filtered command, 13 - 1=illegal command, 0=illegal write/erase region, 12:8- number of filtered commands, 7:0 - command that was filtered
	
    // Crypto DMA to Crypto IP
    logic           dma_nios_master_sel;
    logic           dma_writedata_valid;
    logic [33:0]    dma_writedata;
    logic           sha_done;
    
    logic [24:0]   dma_spi_avmm_mem_address;
    logic [31:0]   dma_spi_avmm_mem_readdata;
    logic          dma_spi_avmm_mem_readdatavalid;
    logic          dma_spi_avmm_mem_waitrequest;
    logic          dma_spi_avmm_mem_read;
    logic [6:0]    dma_spi_avmm_mem_burstcount;

    // bus to mux between which SMBus port for SMBus master to send SMBus traffic 
    logic [2:0] slave_portid;
    
    // DMA to Onchip flash IP avmm interface
    logic           dma_to_ufm_avmm_waitrequest;
    logic [31:0]    dma_to_ufm_avmm_readdata;
    logic           dma_to_ufm_avmm_readdatavalid;
    logic [20:0]    dma_to_ufm_avmm_address;         
    logic           dma_to_ufm_avmm_read;            
    logic [5:0]     dma_to_ufm_avmm_burstcount; 
    
    // GPO to enable DMA to Onchip flash IP path
    logic           dma_ufm_sel;
    
    // I3C
    logic   i3c_pur_oe;
    logic   i3c_scl_data_in;
    logic   i3c_scl_data_out;
    logic   i3c_scl_oe;
    logic   i3c_sda_data_in;
    logic   i3c_sda_data_out;
    logic   i3c_sda_oe;

    logic   i3c_mng_switch_sel_gpo_out;
    logic   i3c_pcie_switch_sel_gpo_out;

    assign PWRGD_AUX_PWRGD_PFR_CPU1 = 1'bz;
    assign FM_PFR_CC_RSVD_2 = 1'bz;
    assign FM_PFR_CC_RSVD_3 = 1'bz;
    assign FM_PFR_CC_RSVD_4 = 1'bz;    
   
    // GPO definition -> 0:selects BMC path (default). Use BMC as proxy to I3C MNG; 1:selects direct PFR to I3C MNG path (bypass BMC as proxy)
    assign i3c_mng_switch_sel_gpo_out = gpo_1[gen_gpo_controls_pkg::GPO_1_I3C_MNG_SWITCH_SEL_BIT_POS];
    
    // GPO definition -> 0:selects BMC path (default). Use BMC as proxy to I3C PCIE; 1:selects direct PFR to I3C PCIE path (bypass BMC as proxy)
    assign i3c_pcie_switch_sel_gpo_out = gpo_1[gen_gpo_controls_pkg::GPO_1_I3C_PCIE_SWITCH_SEL_BIT_POS];
    
    
    assign FM_PFR_MNG_SEL = ~i3c_mng_switch_sel_gpo_out;    // At board level, 0:select PFR direct path; 1:select BMC path (proxy path)
    assign FM_PFR_PCIE_SEL = ~i3c_pcie_switch_sel_gpo_out;  // At board level, 0:select PFR direct path; 1:select BMC path (proxy path)

    pfr_sys u_pfr_sys(
        // System clocks and synchronized resets. Note that sys_clk must be
        // less than 80MHz as it is connected to the dual config IP, and that
        // IP has a max frequency of 80MHz. 
        .sys_clk_clk(sys_clk),
        .spi_clk_clk(spi_clk),
        .i3c_clk_clk(i3c_core_clk),
        
        .sys_clk_reset_reset(!sys_clk_reset_sync_n),
        .spi_clk_reset_reset(!spi_clk_reset_sync_n),
        .i3c_clk_reset_reset(!i3c_core_reset_n),
        
        .global_state_export(global_state),

        .gpo_1_export(gpo_1),
        .gpo_2_export(gpo_2),

        .gpi_1_export(gpi_1),

        // AVMM interface to the timer bank
        .timer_bank_avmm_clk(timer_bank_avmm_clk),
        .timer_bank_avmm_areset(timer_bank_avmm_areset),
        .timer_bank_avmm_address(timer_bank_avmm_address),
        .timer_bank_avmm_waitrequest(timer_bank_avmm_waitrequest),
        .timer_bank_avmm_read(timer_bank_avmm_read),
        .timer_bank_avmm_write(timer_bank_avmm_write),
        .timer_bank_avmm_readdata(timer_bank_avmm_readdata),
        .timer_bank_avmm_writedata(timer_bank_avmm_writedata),

        // AVMM interface to SMBus Mailbox         
        .mailbox_avmm_clk(mailbox_avmm_clk),
        .mailbox_avmm_areset(mailbox_avmm_areset),
        .mailbox_avmm_address(mailbox_avmm_address),
        .mailbox_avmm_waitrequest(mailbox_avmm_waitrequest),
        .mailbox_avmm_read(mailbox_avmm_read),
        .mailbox_avmm_write(mailbox_avmm_write),
        .mailbox_avmm_readdata(mailbox_avmm_readdata),
        .mailbox_avmm_writedata(mailbox_avmm_writedata),
        .mailbox_avmm_readdatavalid(mailbox_avmm_readdatavalid),

        .rfnvram_avmm_clk                  (rfnvram_avmm_clk),
        .rfnvram_avmm_areset               (rfnvram_avmm_areset),
        .rfnvram_avmm_address              (rfnvram_avmm_address),
        .rfnvram_avmm_waitrequest          (rfnvram_avmm_waitrequest),
        .rfnvram_avmm_read                 (rfnvram_avmm_read),
        .rfnvram_avmm_write                (rfnvram_avmm_write),
        .rfnvram_avmm_readdata             (rfnvram_avmm_readdata),
        .rfnvram_avmm_writedata            (rfnvram_avmm_writedata),
        .rfnvram_avmm_readdatavalid        (rfnvram_avmm_readdatavalid),
        // AVMM interfaces to SMBus relay command whitelist memory
        .relay1_avmm_clk        (  ),
        .relay1_avmm_areset     (  ),
        .relay1_avmm_address    ( relay1_avmm_address ),
        .relay1_avmm_waitrequest( '0 ),
        .relay1_avmm_read       (  ),
        .relay1_avmm_write      ( relay1_avmm_write ),
        .relay1_avmm_readdata   ( '0 ),
        .relay1_avmm_writedata  ( relay1_avmm_writedata ),
        .relay2_avmm_clk        (  ),
        .relay2_avmm_areset     (  ),
        .relay2_avmm_address    ( relay2_avmm_address ),
        .relay2_avmm_waitrequest( '0 ),
        .relay2_avmm_read       (  ),
        .relay2_avmm_write      ( relay2_avmm_write ),
        .relay2_avmm_readdata   ( '0 ),
        .relay2_avmm_writedata  ( relay2_avmm_writedata ),
        .relay3_avmm_clk        (  ),
        .relay3_avmm_areset     (  ),
        .relay3_avmm_address    ( relay3_avmm_address ),
        .relay3_avmm_waitrequest( '0 ),
        .relay3_avmm_read       (  ),
        .relay3_avmm_write      ( relay3_avmm_write ),
        .relay3_avmm_readdata   ( '0 ),
        .relay3_avmm_writedata  ( relay3_avmm_writedata ),

        // AVMM interface to the crypto block
        .crypto_avmm_clk(crypto_avmm_clk),
        .crypto_avmm_areset(crypto_avmm_areset),
        .crypto_avmm_address(crypto_avmm_address),
        .crypto_avmm_waitrequest(1'b0),
        .crypto_avmm_read(crypto_avmm_read),
        .crypto_avmm_write(crypto_avmm_write),
        .crypto_avmm_readdata(crypto_avmm_readdata),
        .crypto_avmm_readdatavalid(crypto_avmm_readdatavalid),
        .crypto_avmm_writedata(crypto_avmm_writedata),

        // AVMM interface to the SPI Filter write-enable memories
        .spi_filter_bmc_we_avmm_clk        ( spi_filter_bmc_we_avmm_clk     ),
        .spi_filter_bmc_we_avmm_areset     ( spi_filter_bmc_we_avmm_areset  ),
        .spi_filter_bmc_we_avmm_address    ( spi_filter_bmc_we_avmm_address ),
        .spi_filter_bmc_we_avmm_waitrequest( '0 ),
        .spi_filter_bmc_we_avmm_read       ( spi_filter_bmc_we_avmm_read),
        .spi_filter_bmc_we_avmm_write      ( spi_filter_bmc_we_avmm_write ),
        .spi_filter_bmc_we_avmm_readdata   ( spi_filter_bmc_we_avmm_readdata ),
        .spi_filter_bmc_we_avmm_readdatavalid( spi_filter_bmc_we_avmm_readdatavalid ),
        .spi_filter_bmc_we_avmm_writedata  ( spi_filter_bmc_we_avmm_writedata ),
        .spi_filter_cpu0_flash0_we_avmm_clk        (  ),
        .spi_filter_cpu0_flash0_we_avmm_areset     (  ),
        .spi_filter_cpu0_flash0_we_avmm_address    ( spi_filter_cpu0_flash0_we_avmm_address ),
        .spi_filter_cpu0_flash0_we_avmm_waitrequest( '0 ),
        .spi_filter_cpu0_flash0_we_avmm_read       ( spi_filter_cpu0_flash0_we_avmm_read ),
        .spi_filter_cpu0_flash0_we_avmm_write      ( spi_filter_cpu0_flash0_we_avmm_write ),
        .spi_filter_cpu0_flash0_we_avmm_readdata   ( spi_filter_cpu0_flash0_we_avmm_readdata ),       
        .spi_filter_cpu0_flash0_we_avmm_readdatavalid( spi_filter_cpu0_flash0_we_avmm_readdatavalid ),       
        .spi_filter_cpu0_flash0_we_avmm_writedata  ( spi_filter_cpu0_flash0_we_avmm_writedata ),
		.spi_filter_cpu0_flash1_we_avmm_clk        (  ),
        .spi_filter_cpu0_flash1_we_avmm_areset     (  ),
        .spi_filter_cpu0_flash1_we_avmm_address    ( spi_filter_cpu0_flash1_we_avmm_address ),
        .spi_filter_cpu0_flash1_we_avmm_waitrequest( '0 ),
        .spi_filter_cpu0_flash1_we_avmm_read       ( spi_filter_cpu0_flash1_we_avmm_read ),
        .spi_filter_cpu0_flash1_we_avmm_write      ( spi_filter_cpu0_flash1_we_avmm_write ),
        .spi_filter_cpu0_flash1_we_avmm_readdata   ( spi_filter_cpu0_flash1_we_avmm_readdata ),       
        .spi_filter_cpu0_flash1_we_avmm_readdatavalid( spi_filter_cpu0_flash1_we_avmm_readdatavalid ),       
        .spi_filter_cpu0_flash1_we_avmm_writedata  ( spi_filter_cpu0_flash1_we_avmm_writedata ),
        .spi_filter_cpu1_flash0_we_avmm_clk        (  ),
        .spi_filter_cpu1_flash0_we_avmm_areset     (  ),
        .spi_filter_cpu1_flash0_we_avmm_address    ( spi_filter_cpu1_flash0_we_avmm_address ),
        .spi_filter_cpu1_flash0_we_avmm_waitrequest( '0 ),
        .spi_filter_cpu1_flash0_we_avmm_read       ( spi_filter_cpu1_flash0_we_avmm_read ),
        .spi_filter_cpu1_flash0_we_avmm_write      ( spi_filter_cpu1_flash0_we_avmm_write ),
        .spi_filter_cpu1_flash0_we_avmm_readdata   ( spi_filter_cpu1_flash0_we_avmm_readdata ),       
        .spi_filter_cpu1_flash0_we_avmm_readdatavalid( spi_filter_cpu1_flash0_we_avmm_readdatavalid ),       
        .spi_filter_cpu1_flash0_we_avmm_writedata  ( spi_filter_cpu1_flash0_we_avmm_writedata ),
		.spi_filter_cpu1_flash1_we_avmm_clk        (  ),
        .spi_filter_cpu1_flash1_we_avmm_areset     (  ),
        .spi_filter_cpu1_flash1_we_avmm_address    ( spi_filter_cpu1_flash1_we_avmm_address ),
        .spi_filter_cpu1_flash1_we_avmm_waitrequest( '0 ),
        .spi_filter_cpu1_flash1_we_avmm_read       ( spi_filter_cpu1_flash1_we_avmm_read ),
        .spi_filter_cpu1_flash1_we_avmm_write      ( spi_filter_cpu1_flash1_we_avmm_write ),
        .spi_filter_cpu1_flash1_we_avmm_readdata   ( spi_filter_cpu1_flash1_we_avmm_readdata ),       
        .spi_filter_cpu1_flash1_we_avmm_readdatavalid( spi_filter_cpu1_flash1_we_avmm_readdatavalid ),       
        .spi_filter_cpu1_flash1_we_avmm_writedata  ( spi_filter_cpu1_flash1_we_avmm_writedata ),

        // AVMM interface to the SPI filter CSR
        .spi_filter_csr_avmm_clk            (  ),
        .spi_filter_csr_avmm_areset         (  ),
        .spi_filter_csr_avmm_address        (spi_master_csr_avmm_address),
        .spi_filter_csr_avmm_waitrequest    (spi_master_csr_avmm_waitrequest),
        .spi_filter_csr_avmm_read           (spi_master_csr_avmm_read),
        .spi_filter_csr_avmm_write          (spi_master_csr_avmm_write),
        .spi_filter_csr_avmm_readdata       (spi_master_csr_avmm_readdata),
        .spi_filter_csr_avmm_readdatavalid  (spi_master_csr_avmm_readdatavalid),
        .spi_filter_csr_avmm_writedata      (spi_master_csr_avmm_writedata),

        // AVMM interface to the SPI filter
        .spi_filter_avmm_clk                (  ),
        .spi_filter_avmm_areset             (  ),
        .spi_filter_avmm_address            (spi_master_avmm_address),
        .spi_filter_avmm_waitrequest        (spi_master_avmm_waitrequest),
        .spi_filter_avmm_read               (spi_master_avmm_read),
        .spi_filter_avmm_write              (spi_master_avmm_write),
        .spi_filter_avmm_readdata           (spi_master_avmm_readdata),
        .spi_filter_avmm_readdatavalid      (spi_master_avmm_readdatavalid),
        .spi_filter_avmm_writedata          (spi_master_avmm_writedata),
	
        // AVMM interface from Crypto DMA to UFM
        .dma_to_ufm_avmm_clk            (),     
        .dma_to_ufm_avmm_areset		    (), 
        .dma_to_ufm_avmm_address		(dma_to_ufm_avmm_address),         
        .dma_to_ufm_avmm_waitrequest	(dma_to_ufm_avmm_waitrequest),      
        .dma_to_ufm_avmm_read		    (dma_to_ufm_avmm_read),            
        .dma_to_ufm_avmm_write		    (1'b0),             
        .dma_to_ufm_avmm_readdata		(dma_to_ufm_avmm_readdata),     
        .dma_to_ufm_avmm_writedata		(32'b0),        
        .dma_to_ufm_avmm_readdatavalid	(dma_to_ufm_avmm_readdatavalid),
        .dma_to_ufm_avmm_burstcount		(dma_to_ufm_avmm_burstcount), 

        // AVMM interface to Crypto DMA
        .crypto_dma_avmm_clk                (crypto_dma_avmm_clk),
        .crypto_dma_avmm_areset             (crypto_dma_avmm_areset),
        .crypto_dma_avmm_address            (crypto_dma_avmm_address),
        .crypto_dma_avmm_waitrequest        (1'b0),
        .crypto_dma_avmm_read               (crypto_dma_avmm_read),
        .crypto_dma_avmm_write              (crypto_dma_avmm_write),
        .crypto_dma_avmm_readdata           (crypto_dma_avmm_readdata),
        .crypto_dma_avmm_writedata          (crypto_dma_avmm_writedata),
        
        // AVMM interface to I3C
        .i3c_avmm_clk                (i3c_avmm_clk),
        .i3c_avmm_areset             (i3c_avmm_areset),
        .i3c_avmm_address            (i3c_avmm_address),
        .i3c_avmm_waitrequest        (i3c_avmm_waitrequest),
        .i3c_avmm_read               (i3c_avmm_read),
        .i3c_avmm_write              (i3c_avmm_write),
        .i3c_avmm_readdata           (i3c_avmm_readdata),
        .i3c_avmm_readdatavalid      (i3c_avmm_readdatavalid),
        .i3c_avmm_writedata          (i3c_avmm_writedata),

        //AVMM interface to AES-256 GCM
        .aes256_gcm_avmm_clk           (aes256_gcm_avmm_clk        ),
        .aes256_gcm_avmm_areset        (aes256_gcm_avmm_areset     ),
        .aes256_gcm_avmm_address       (aes256_gcm_avmm_address    ),
        .aes256_gcm_avmm_waitrequest   (aes256_gcm_avmm_waitrequest),
        .aes256_gcm_avmm_read          (aes256_gcm_avmm_read       ),
        .aes256_gcm_avmm_readdatavalid (aes256_gcm_avmm_readdatavalid),
        .aes256_gcm_avmm_write         (aes256_gcm_avmm_write      ),
        .aes256_gcm_avmm_readdata      (aes256_gcm_avmm_readdata   ),
        .aes256_gcm_avmm_writedata     (aes256_gcm_avmm_writedata  )
    );

	
    ///////////////////////////////////////////////////////////////////////////
    // GPI Connectivity
    ///////////////////////////////////////////////////////////////////////////
    reg rearm_acm_timer;
    reg hold_pltrst_in_seamless;
    
    // CPU and BMC resets from common core
    // TODO Clean up gen gpi list and include PWRGD_AUX_PWRGD_CPU1
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_CC_CPU0_PLT_AUX_PWRGD_BIT_POS] = PWRGD_AUX_PWRGD_CPU0;
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_CC_RST_SRST_BMC_PLD_R_N_BIT_POS] = RST_SRST_BMC_PFR_N;

    assign gpi_1[gen_gpi_signals_pkg::GPI_1_PLTRST_DETECTED_REARM_ACM_TIMER_BIT_POS] = rearm_acm_timer;

    // status bit from the SPI filter block
    logic spi_control_bmc_ibb_access_detected;
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_BMC_SPI_IBB_ACCESS_DETECTED_BIT_POS] = spi_control_bmc_ibb_access_detected;

    assign gpi_1[gen_gpi_signals_pkg::GPI_1_PFR_FORCE_RECOVERY_N_BIT_POS] = FM_PFR_FORCE_RECOVERY_N;
    // HPFR Inputs
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_HPFR_IN_BIT_POS] = FM_HPFR_IN;
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_HPFR_ACTIVE_BIT_POS] = FM_HPFR_ACTIVE;
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_LEGACY_BIT_POS] = FM_HPFR_LEGACY;
    
    // PLTRST_SYNC
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_RST_PLTRST_CPU0_N_BIT_POS] = RST_PLTRST_CPU0_N;
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_RST_PLTRST_CPU1_N_BIT_POS] = RST_PLTRST_CPU1_N;
    
	// reserved signal
	logic [5:0] oPData_reserved;
	logic FM_CPU1_SKTOCC_LVT3_N;
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_FM_CPU1_SKTOCC_LVT3_N_BIT_POS] = FM_CPU1_SKTOCC_LVT3_N;
	logic FM_CPU0_SKTOCC_LVT3_N;
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_FM_CPU0_SKTOCC_LVT3_N_BIT_POS] = FM_CPU0_SKTOCC_LVT3_N;
	// cpu powergood - to distinguish the warm reset and cold reset
	logic PWRGD_CPU0_LVC3;
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_PWRGD_CPU0_LVC3_BIT_POS] = PWRGD_CPU0_LVC3;
	// RSU IP hide done
	logic RSU_IP_HIDE_DONE;
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_RSU_IP_HIDE_DONE_BIT_POS] = RSU_IP_HIDE_DONE;
	// SGPIO SMB board ID signals
	logic SCM_BOARD_ID_0;	
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_SCM_BOARD_ID_0_BIT_POS] = SCM_BOARD_ID_0;
	logic SCM_BOARD_ID_1;	
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_SCM_BOARD_ID_1_BIT_POS] = SCM_BOARD_ID_1;
	logic SCM_BOARD_ID_2;	
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_SCM_BOARD_ID_2_BIT_POS] = SCM_BOARD_ID_2;
	logic SCM_BOARD_ID_3;	
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_SCM_BOARD_ID_3_BIT_POS] = SCM_BOARD_ID_3;
	logic SCM_BOARD_ID_4;	
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_SCM_BOARD_ID_4_BIT_POS] = SCM_BOARD_ID_4;
	logic SCM_BOARD_ID_5;	
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_SCM_BOARD_ID_5_BIT_POS] = SCM_BOARD_ID_5;
	
    assign gpi_1[31:gen_gpi_signals_pkg::GPI_1_UNUSED_BITS_START_BIT_POS] = '0;


    
    ///////////////////////////////////////////////////////////////////////////
    // GPO Connectivity
    ///////////////////////////////////////////////////////////////////////////

    assign RST_SRST_BMC_SCM_FPGA_N = gpo_1[gen_gpo_controls_pkg::GPO_1_RST_SRST_BMC_PLD_R_N_BIT_POS] & PWRGD_AUX_PWRGD_CPU0;
    // CPU Reset. Active low
    assign PWRGD_AUX_PWRGD_PFR_CPU0 = (gpo_1[gen_gpo_controls_pkg::GPO_1_PFR_CPU0_PLT_AUX_PWRGD_BIT_POS]) ? PWRGD_AUX_PWRGD_CPU0 : 1'b0;
    
    // Mux select pins
    assign FM_PFR_CPU0_SPI_MASTERSEL = gpo_1[gen_gpo_controls_pkg::GPO_1_CPU0_SPI_MASTERSEL_BIT_POS];
    // BMC SPI Mux. 0-BMC, 1-CPLD
    assign FM_PFR_BMC_SPI_MASTERSEL = gpo_1[gen_gpo_controls_pkg::GPO_1_BMC_SPI_MASTERSEL_BIT_POS];
    // CPU1 SPI Mux. 0-CPU1, 1-CPLD
    assign FM_PFR_CPU1_SPI_MASTERSEL = gpo_1[gen_gpo_controls_pkg::GPO_1_CPU1_SPI_MASTERSEL_BIT_POS];
    
    // BMC external reset. Used for BMC only update
    
    assign RST_PFR_BMC_EXTRST_N = gpo_1[gen_gpo_controls_pkg::GPO_1_RST_PFR_EXTRST_N_BIT_POS];
    
    // pin to allow clear the pltrest detect register
    wire clear_pltrst_detect_flag;
    assign clear_pltrst_detect_flag = gpo_1[gen_gpo_controls_pkg::GPO_1_CLEAR_PLTRST_DETECT_FLAG_BIT_POS];

    ///////////////////////////////////////////////////////////////////////////
    // PLTRST_N edge detect   
    ///////////////////////////////////////////////////////////////////////////
    reg pltrst_reg;
    
    always_ff @(posedge sys_clk or posedge timer_bank_avmm_areset) begin
        if (timer_bank_avmm_areset) begin
            pltrst_reg <= 1'b0;
            rearm_acm_timer <=1'b0;
        end else begin 
            pltrst_reg <= RST_PLTRST_CPU0_PFR_LVC3_N;
            if (!pltrst_reg & RST_PLTRST_CPU0_PFR_LVC3_N) begin
                rearm_acm_timer <= 1'b1;
            end
            if (clear_pltrst_detect_flag) begin
                rearm_acm_timer <= 1'b0;
            end
        end
    end
    
    always_ff @(posedge sys_clk or posedge timer_bank_avmm_areset) begin
        if (timer_bank_avmm_areset) begin
            hold_pltrst_in_seamless <= 1'b0;
        end else begin 
            if (pltrst_reg & !RST_PLTRST_CPU0_N & FM_PFR_CPU0_SPI_MASTERSEL) begin
                hold_pltrst_in_seamless <= 1'b1;
            end
            if (!FM_PFR_CPU0_SPI_MASTERSEL) begin
                hold_pltrst_in_seamless <= 1'b0;
            end
        end
    end

    // SMBus Relay control pins
    logic relay1_block_disable;
    logic relay1_filter_disable;
    logic relay1_all_addresses;
    assign relay1_block_disable  = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY1_BLOCK_DISABLE_BIT_POS] ;
    assign relay1_filter_disable = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY1_FILTER_DISABLE_BIT_POS];
    assign relay1_all_addresses  = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY1_ALL_ADDRESSES_BIT_POS];
    logic relay2_block_disable;
    logic relay2_filter_disable;
    logic relay2_all_addresses;
    assign relay2_block_disable  = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY2_BLOCK_DISABLE_BIT_POS] ;
    assign relay2_filter_disable = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY2_FILTER_DISABLE_BIT_POS];
    assign relay2_all_addresses  = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY2_ALL_ADDRESSES_BIT_POS];
    logic relay3_block_disable;
    logic relay3_filter_disable;
    logic relay3_all_addresses;
    assign relay3_block_disable  = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY3_BLOCK_DISABLE_BIT_POS] ;
    assign relay3_filter_disable = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY3_FILTER_DISABLE_BIT_POS];
    assign relay3_all_addresses  = gpo_1[gen_gpo_controls_pkg::GPO_1_RELAY3_ALL_ADDRESSES_BIT_POS];


    // SPI control block control pins
    logic spi_control_pfr_bmc_master_sel;
    logic spi_control_pfr_pch_master_sel;
    logic spi_control_pfr_cpu1_master_sel;
    logic spi_control_spi_master_bmc_pchn;
    logic spi_control_spi_master_path_sel;
    logic spi_control_bmc_filter_disable;
    logic spi_control_pch_filter_disable;
    logic spi_control_cpu1_filter_disable;
    logic spi_control_bmc_clear_ibb_detected;
    logic spi_control_bmc_addr_mode_set_3b;
    
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_SPI_MASTER_BMC_PCHN_BIT_POS] = gpo_1[gen_gpo_controls_pkg::GPO_1_SPI_MASTER_BMC_PCHN_BIT_POS];
    assign gpi_1[gen_gpi_signals_pkg::GPI_1_SPI_MASTER_PATH_SEL_BIT_POS] = gpo_1[gen_gpo_controls_pkg::GPO_1_SPI_MASTER_PATH_SEL_BIT_POS];
    
    assign spi_control_pfr_bmc_master_sel       = gpo_1[gen_gpo_controls_pkg::GPO_1_BMC_SPI_MASTERSEL_BIT_POS];
    assign spi_control_pfr_pch_master_sel       = gpo_1[gen_gpo_controls_pkg::GPO_1_CPU0_SPI_MASTERSEL_BIT_POS];
    assign spi_control_pfr_cpu1_master_sel      = gpo_1[gen_gpo_controls_pkg::GPO_1_CPU1_SPI_MASTERSEL_BIT_POS];
    assign spi_control_spi_master_bmc_pchn      = gpo_1[gen_gpo_controls_pkg::GPO_1_SPI_MASTER_BMC_PCHN_BIT_POS];
    assign spi_control_spi_master_path_sel      = gpo_1[gen_gpo_controls_pkg::GPO_1_SPI_MASTER_PATH_SEL_BIT_POS];
    assign spi_control_bmc_filter_disable       = gpo_1[gen_gpo_controls_pkg::GPO_1_BMC_SPI_FILTER_DISABLE_BIT_POS];
    assign spi_control_pch_filter_disable       = gpo_1[gen_gpo_controls_pkg::GPO_1_PCH_SPI_FILTER_DISABLE_BIT_POS];
    assign spi_control_cpu1_filter_disable      = gpo_1[gen_gpo_controls_pkg::GPO_1_CPU1_SPI_FILTER_DISABLE_BIT_POS];
    assign spi_control_bmc_clear_ibb_detected   = gpo_1[gen_gpo_controls_pkg::GPO_1_BMC_SPI_CLEAR_IBB_DETECTED_BIT_POS];
    assign spi_control_bmc_addr_mode_set_3b     = gpo_1[gen_gpo_controls_pkg::GPO_1_BMC_SPI_ADDR_MODE_SET_3B_BIT_POS];
    
    assign PFR_CPU0_RTC_RST_N = (gpo_1[gen_gpo_controls_pkg::GPO_1_PFR_CPU0_RTC_RST_BIT_POS]) ? 1'b0 : 1'bZ; 
    assign PFR_CPU1_RTC_RST_N = (gpo_1[gen_gpo_controls_pkg::GPO_1_PFR_CPU1_RTC_RST_BIT_POS]) ? 1'b0 : 1'bZ; 

    // HPFR output
    assign FM_HPFR_OUT = gpo_1[gen_gpo_controls_pkg::GPO_1_HPFR_OUT_BIT_POS];
    
    // Path to Crypto IP and SPI Master IP
    assign dma_nios_master_sel = gpo_1[gen_gpo_controls_pkg::GPO_1_DMA_NIOS_MASTER_SEL_BIT_POS];
    
    // DMA to Onchip flash IP path
    assign dma_ufm_sel = gpo_1[gen_gpo_controls_pkg::GPO_1_DMA_UFM_SEL_BIT_POS];
    

    assign FP_PWR_BTN_PFR_N = FP_BMC_PWR_BTN_N;
    assign FP_ID_LED_N = FP_ID_LED_BMC_N;
    assign FP_LED_STATUS_AMBER_N = FP_LED_STATUS_AMBER_BMC_N;
    assign FP_LED_STATUS_GREEN_N = FP_LED_STATUS_GREEN_BMC_N;
    
    // SPI 
    assign RST_PFR_BMC_SPI_RESET_N = gpo_1[gen_gpo_controls_pkg::GPO_1_PFR_BMC_SPI_RESET_N_BIT_POS];
    assign RST_SPI_PFR_CPU0_RESET_N = gpo_1[gen_gpo_controls_pkg::GPO_1_PFR_CPU0_SPI_RESET_N_BIT_POS];
    assign RST_SPI_PFR_CPU1_N = gpo_2[gen_gpo_controls_pkg::GPO_2_PFR_CPU1_SPI_RESET_N_BIT_POS];
    assign RST_SPI_PFR_RESET_N = gpo_2[gen_gpo_controls_pkg::GPO_2_RST_SPI_PFR_RESET_N_BIT_POS];
    
	// SMB CPLD UPDATE I2C interface selection  
	logic SCM_CPLD_UPDATE_HIDE;
	assign FM_PFR_SMB_CPLD_UPDATE_SEL = gpo_2[gen_gpo_controls_pkg::GPO_2_PFR_SMB_CPLD_UPDATE_SEL_N_BIT_POS];	
	assign SCM_CPLD_UPDATE_HIDE = gpo_2[gen_gpo_controls_pkg::GPO_2_SCM_CPLD_UPDATE_HIDE_BIT_POS];
	 
    ///////////////////////////////////////////////////////////////////////////
    // Timer bank
    ///////////////////////////////////////////////////////////////////////////
    timer_bank u_timer_bank (
        .clk(timer_bank_avmm_clk),
        .areset(timer_bank_avmm_areset),
        .clk2M(clk2M),
        
        .avmm_address(timer_bank_avmm_address),
        .avmm_read(timer_bank_avmm_read),
        .avmm_write(timer_bank_avmm_write),
        .avmm_readdata(timer_bank_avmm_readdata),
        .avmm_writedata(timer_bank_avmm_writedata)
    );
    assign timer_bank_avmm_waitrequest = 1'b0;

    ///////////////////////////////////////////////////////////////////////////
    // Crypto block
    ///////////////////////////////////////////////////////////////////////////
    crypto_top #
    (
        .ENABLE_CRYPTO_256  (platform_defs_pkg::ENABLE_CRYPTO_256),
        .ENABLE_CRYPTO_384  (platform_defs_pkg::ENABLE_CRYPTO_384),
        .USE_ECDSA_BLOCK    (1)
    ) u_crypto (
        .clk(crypto_avmm_clk),
        .areset(crypto_avmm_areset),
       
        .csr_address(crypto_avmm_address),
        .csr_read(crypto_avmm_read),
        .csr_write(crypto_avmm_write),
        .csr_readdata(crypto_avmm_readdata),
        .csr_readdatavalid(crypto_avmm_readdatavalid),
        .csr_writedata(crypto_avmm_writedata),

        .dma_nios_master_sel(dma_nios_master_sel || dma_ufm_sel), // Either one set enables DMA path to SHA block
        .dma_writedata_valid(dma_writedata_valid),
        .dma_writedata(dma_writedata),
        .sha_done(sha_done)
    );
	 
    ///////////////////////////////////////////////////////////////////////////
    // Crypto DMA
    ///////////////////////////////////////////////////////////////////////////
    crypto_dma #(
        .ADDRESS_WIDTH_SPI  (platform_defs_pkg::CRYPTO_DMA_SPI_ADDRESS_WIDTH), // in word addressing format based on the largest supported flash device in platform
        .ADDRESS_WIDTH_UFM  (platform_defs_pkg::CRYPTO_DMA_UFM_ADDRESS_WIDTH) 
    ) u_crypto_dma (
        .spi_clk                (spi_clk),
        .spi_clk_areset         (~spi_clk_reset_sync_n),
        .spi_mm_address         (dma_spi_avmm_mem_address),
        .spi_mm_read            (dma_spi_avmm_mem_read),
        .spi_mm_burstcount      (dma_spi_avmm_mem_burstcount),
        .spi_mm_readdata        (dma_spi_avmm_mem_readdata),
        .spi_mm_readdatavalid   (dma_spi_avmm_mem_readdatavalid),
        .spi_mm_waitrequest     (dma_spi_avmm_mem_waitrequest),
        .ufm_mm_address         (dma_to_ufm_avmm_address),
        .ufm_mm_read            (dma_to_ufm_avmm_read),
        .ufm_mm_burstcount      (dma_to_ufm_avmm_burstcount),
        .ufm_mm_readdata        (dma_to_ufm_avmm_readdata),
        .ufm_mm_readdatavalid   (dma_to_ufm_avmm_readdatavalid),
        .ufm_mm_waitrequest     (dma_to_ufm_avmm_waitrequest),
        .csr_read               (crypto_dma_avmm_read),      
        .csr_write              (crypto_dma_avmm_write),     
        .csr_writedata          (crypto_dma_avmm_writedata),    
        .csr_address            (crypto_dma_avmm_address),     
        .csr_readdata           (crypto_dma_avmm_readdata),                
        .sys_clk                (crypto_dma_avmm_clk),     
        .sys_clk_areset         (crypto_dma_avmm_areset),     
        .wr_data                (dma_writedata),
        .wr_data_valid          (dma_writedata_valid),
        .sha_done               (sha_done),
        .dma_ufm_sel            (dma_ufm_sel)
 
    );

    ///////////////////////////////////////////////////////////////////////////
    // SMBus mailbox
    ///////////////////////////////////////////////////////////////////////////

    logic bmc_mailbox_slave_scl_in;
    logic bmc_mailbox_slave_scl_oe;
    logic bmc_mailbox_slave_sda_in;
    logic bmc_mailbox_slave_sda_oe;

    logic pch_mailbox_slave_scl_in;
    logic pch_mailbox_slave_scl_oe;
    logic pch_mailbox_slave_sda_in;
    logic pch_mailbox_slave_sda_oe;
    
    logic rfnvram_sda_in;
    logic rfnvram_sda_oe;
    logic rfnvram_scl_in;
    logic rfnvram_scl_oe;
    
    logic pcie_mailbox_slave_scl_in;
    logic pcie_mailbox_slave_scl_oe;
    logic pcie_mailbox_slave_sda_in;
    logic pcie_mailbox_slave_sda_oe;
    
    smbus_mailbox #(
        .BMC_SMBUS_ADDRESS(platform_defs_pkg::BMC_SMBUS_MAILBOX_ADDR),
        .PCIE_SMBUS_ADDRESS(platform_defs_pkg::PCIE_SMBUS_MAILBOX_ADDR)
    ) u_smbus_mailbox (
        .clk(mailbox_avmm_clk),
        .i_resetn(!mailbox_avmm_areset),
        .slave_portid(slave_portid),
        .ia_bmc_slave_sda_in(bmc_mailbox_slave_sda_in),
        .o_bmc_slave_sda_oe(bmc_mailbox_slave_sda_oe), 
        .ia_bmc_slave_scl_in(bmc_mailbox_slave_scl_in),
        .o_bmc_slave_scl_oe(bmc_mailbox_slave_scl_oe),
        .ia_pcie_slave_sda_in(pcie_mailbox_slave_sda_in),
        .o_pcie_slave_sda_oe(pcie_mailbox_slave_sda_oe), 
        .ia_pcie_slave_scl_in(pcie_mailbox_slave_scl_in),
        .o_pcie_slave_scl_oe(pcie_mailbox_slave_scl_oe),

        .m0_read(mailbox_avmm_read),
        .m0_write(mailbox_avmm_write),
        .m0_writedata(mailbox_avmm_writedata),
        .m0_readdata(mailbox_avmm_readdata),
        .m0_address(mailbox_avmm_address),
        .m0_readdatavalid(mailbox_avmm_readdatavalid)
    );

    assign SMB_HSBP_BMC_SCL_LVC3 = ((rfnvram_scl_oe && (slave_portid == 3'b010)) || bmc_mailbox_slave_scl_oe) ? 1'b0 : 1'bz;
    assign SMB_HSBP_BMC_SDA_LVC3 = ((rfnvram_sda_oe && (slave_portid == 3'b010)) || bmc_mailbox_slave_sda_oe) ? 1'b0 : 1'bz;
    assign bmc_mailbox_slave_scl_in = SMB_HSBP_BMC_SCL_LVC3;
    assign bmc_mailbox_slave_sda_in = SMB_HSBP_BMC_SDA_LVC3;
    
    assign SMB_PCIE_PFR_SCL_LVC3_R1 = ((rfnvram_scl_oe && (slave_portid == 3'b011)) || pcie_mailbox_slave_scl_oe) ? 1'b0 : 1'bz;
    assign SMB_PCIE_PFR_SDA_LVC3_R1 = ((rfnvram_sda_oe && (slave_portid == 3'b011)) || pcie_mailbox_slave_sda_oe) ? 1'b0 : 1'bz;
    assign pcie_mailbox_slave_scl_in = SMB_PCIE_PFR_SCL_LVC3_R1;
    assign pcie_mailbox_slave_sda_in = SMB_PCIE_PFR_SDA_LVC3_R1;

    // Use rfnvram as I2C master for online platform CPLD update
    assign SMB_CPLD_UPDATE_PFR_SCL_LVC3_R = (rfnvram_scl_oe && (slave_portid == 3'b001)) ? 1'b0 : 1'bz;
    assign SMB_CPLD_UPDATE_PFR_SDA_LVC3_R = (rfnvram_sda_oe && (slave_portid == 3'b001)) ? 1'b0 : 1'bz;
    
    // Use rfnvram as I2C master for I3C PCIE interface (PCIE devices not ready to support I3C yet
    assign I3C_PFR_PCIE_SCL = (rfnvram_scl_oe && (slave_portid == 3'b111)) ? 1'b0 : 1'bz;
    assign I3C_PFR_PCIE_SDA = (rfnvram_sda_oe && (slave_portid == 3'b111)) ? 1'b0 : 1'bz;
    assign FM_I3C_PFR_PCIE_PUR_EN = 1'b1; // always turn-on open-drain mode in I2C use-case
    
    assign mailbox_avmm_waitrequest =1'b0;

    ///////////////////////////////////////////////////////////////////////////
    // RFNVRAM Master
    ///////////////////////////////////////////////////////////////////////////

    rfnvram_smbus_master #(.FIFO_DEPTH(platform_defs_pkg::RFNVRAM_FIFO_SIZE), .CLOCK_PERIOD_PS(platform_defs_pkg::SYS_CLOCK_PERIOD_PS))
    u_rfnvram_master (
        .clk(rfnvram_avmm_clk),
        .resetn(!rfnvram_avmm_areset),

        // AVMM interface to connect the NIOS to the CSR interface
        .csr_address(rfnvram_avmm_address),
        .csr_read(rfnvram_avmm_read),
        .csr_readdata(rfnvram_avmm_readdata),
        .csr_write(rfnvram_avmm_write),
        .csr_writedata(rfnvram_avmm_writedata),
        .csr_readdatavalid(rfnvram_avmm_readdatavalid),
        
        .slave_portid(slave_portid),

        .sda_in(rfnvram_sda_in),
        .sda_oe(rfnvram_sda_oe),
        .scl_in(rfnvram_scl_in),
        .scl_oe(rfnvram_scl_oe)

    );

    assign SMB_PFR_RFID_SCL = (rfnvram_scl_oe && (slave_portid == 3'b000)) ? 1'b0 : 1'bz;
    assign SMB_PFR_RFID_SDA = (rfnvram_sda_oe && (slave_portid == 3'b000)) ? 1'b0 : 1'bz;
    assign rfnvram_scl_in = (slave_portid == 3'b000) ? SMB_PFR_RFID_SCL :
                            (slave_portid == 3'b001) ? SMB_CPLD_UPDATE_PFR_SCL_LVC3_R : 
                            (slave_portid == 3'b010) ? SMB_HSBP_BMC_SCL_LVC3 : 
                            (slave_portid == 3'b011) ? SMB_PCIE_PFR_SCL_LVC3_R1 : 
                            (slave_portid == 3'b100) ? SMB_PMBUS1_BMC_LVC3_SCL : 
                            (slave_portid == 3'b101) ? SMB_PMBUS2_BMC_LVC3_SCL : 
                            (slave_portid == 3'b110) ? SMB_HSBP_BMC_SCL_LVC3 : I3C_PFR_PCIE_SCL;
    
    assign rfnvram_sda_in = (slave_portid == 3'b000) ? SMB_PFR_RFID_SDA :
                            (slave_portid == 3'b001) ? SMB_CPLD_UPDATE_PFR_SDA_LVC3_R : 
                            (slave_portid == 3'b010) ? SMB_HSBP_BMC_SDA_LVC3 : 
                            (slave_portid == 3'b011) ? SMB_PCIE_PFR_SDA_LVC3_R1 : 
                            (slave_portid == 3'b100) ? SMB_PMBUS1_BMC_LVC3_SDA : 
                            (slave_portid == 3'b101) ? SMB_PMBUS2_BMC_LVC3_SDA : 
                            (slave_portid == 3'b110) ? SMB_HSBP_BMC_SDA_LVC3 : I3C_PFR_PCIE_SDA;
    assign rfnvram_avmm_waitrequest = 1'b0;

    ///////////////////////////////////////////////////////////////////////////
    // SPI Filter and master
    ///////////////////////////////////////////////////////////////////////////

    // signals for acting as SPI bus master on the BMC SPI bus
    logic [3:0]                          bmc_spi_master_data_in;        // data signals from the SPI data pins
    logic [3:0]                          bmc_spi_master_data_out;       // data signals driven to the SPI data pins
    logic [3:0]                          bmc_spi_master_data_oe;        // when asserted, bmc_spi_data drives the respective BMC SPI data pin

    // signals for acting as SPI bus master on the PCH SPI bus
    logic [3:0]                          pch_spi_master_data_in;        // data signals from the SPI data pins
    logic [3:0]                          pch_spi_master_data_out;       // data signals driven to the SPI data pins
    logic [3:0]                          pch_spi_master_data_oe;        // when asserted, pch_spi_data drives the respective PCH SPI data pin
    
    // signals for acting as SPI bus master on the CPU1 SPI bus
    logic [3:0]                          cpu1_spi_master_data_in;        // data signals from the SPI data pins
    logic [3:0]                          cpu1_spi_master_data_out;       // data signals driven to the SPI data pins
    logic [3:0]                          cpu1_spi_master_data_oe;        // when asserted, cpu1_spi_data drives the respective CPU1 SPI data pin
    
    // signals for acting as SPI bus master on the PFR Flash bus
    logic [3:0]                          pfr_spi_master_data_in;        // data signals from the SPI data pins
    logic [3:0]                          pfr_spi_master_data_out;       // data signals driven to the SPI data pins
    logic [3:0]                          pfr_spi_master_data_oe;        // when asserted, pfr_spi_data drives the respective PFR Flash SPI data pin
    
    localparam  BMC_ENABLE_COMMAND_LOG = 0;
    localparam  PCH_ENABLE_COMMAND_LOG = 0;
    localparam  CPU1_ENABLE_COMMAND_LOG = 0;
    
    spi_control #(
        .BMC_IBB_ADDRESS_MSBS       ( platform_defs_pkg::BMC_IBB_ADDRESS_MSBS   ),
        .BMC_FLASH_ADDRESS_BITS     ( platform_defs_pkg::BMC_FLASH_ADDRESS_BITS ),
        .PCH_FLASH_ADDRESS_BITS     ( platform_defs_pkg::PCH_FLASH_ADDRESS_BITS ),
        .CPU1_FLASH_ADDRESS_BITS    ( platform_defs_pkg::CPU1_FLASH_ADDRESS_BITS ),
        .BMC_ENABLE_COMMAND_LOG     ( BMC_ENABLE_COMMAND_LOG                    ),
        .PCH_ENABLE_COMMAND_LOG     ( PCH_ENABLE_COMMAND_LOG                    ),
        .CPU1_ENABLE_COMMAND_LOG    ( CPU1_ENABLE_COMMAND_LOG                   )
    ) u_spi_control (
        .clock                      ( spi_clk                               ),
        .i_resetn                   ( spi_clk_reset_sync_n                  ),
        .sys_clock                  ( spi_filter_bmc_we_avmm_clk            ),
        .i_sys_resetn               ( !spi_filter_bmc_we_avmm_areset        ),
        .o_bmc_spi_master_sclk      ( SPI_CLK_OPFR_BMC_LVC3             ),  // connect directly to output pin
        .i_bmc_spi_master_data      ( bmc_spi_master_data_in                ),
        .o_bmc_spi_master_data      ( bmc_spi_master_data_out               ),
        .o_bmc_spi_master_data_oe   ( bmc_spi_master_data_oe                ),
        .o_pch_spi_master_sclk      ( SPI_CLK_OPFR_CPU0_LVC18                     ),  // connect directly to output pin
        .i_pch_spi_master_data      ( pch_spi_master_data_in                ),
        .o_pch_spi_master_data      ( pch_spi_master_data_out               ),
        .o_pch_spi_master_data_oe   ( pch_spi_master_data_oe                ),
        .o_cpu1_spi_master_sclk     ( SPI_CPU1_PFR_CTRL_CLK                 ),  // connect directly to output pin
        .i_cpu1_spi_master_data     ( cpu1_spi_master_data_in               ),
        .o_cpu1_spi_master_data     ( cpu1_spi_master_data_out              ),
        .o_cpu1_spi_master_data_oe  ( cpu1_spi_master_data_oe               ),
        .o_pfr_spi_master_sclk      ( SPI_PFR_CLK                           ),  // connect directly to output pin
        .i_pfr_spi_master_data      ( pfr_spi_master_data_in                ),
        .o_pfr_spi_master_data      ( pfr_spi_master_data_out               ),
        .o_pfr_spi_master_data_oe   ( pfr_spi_master_data_oe                ),
        
        .clk_bmc_spi_mon_sclk       ( SPI_BMC_PFR_MON_CLK              ),
        .i_bmc_spi_mon_mosi         ( SPI_BMC_PFR_MON_IO0             ),
        .i_bmc_spi_mon_csn          ( SPI_BMC_PFR_MON_CS0_N                     ),
        .clk_pch_spi_mon_sclk       ( SPI_CPU0_PFR_MON_CLK        ),
        .i_pch_spi_mon_data         ( {SPI_CPU0_PFR_MON_IO3, SPI_CPU0_PFR_MON_IO2, SPI_CPU0_PFR_MON_IO1, SPI_CPU0_PFR_MON_IO0} ),
        .i_pch_spi_mon_csn          ( {SPI_CPU0_PFR_MON_CS1_SWAP_N, SPI_CPU0_PFR_MON_CS0_SWAP_N}                     ),
        .clk_cpu1_spi_mon_sclk      ( SPI_CPU1_PFR_MON_CLK                  ),
        .i_cpu1_spi_mon_data        ( {SPI_CPU1_PFR_MON_IO3, SPI_CPU1_PFR_MON_IO2, SPI_CPU1_PFR_MON_IO1, SPI_CPU1_PFR_MON_IO0} ),
        .i_cpu1_spi_mon_csn         ( {SPI_CPU1_PFR_MON_CS1_N, SPI_CPU1_PFR_MON_CS0_N}                ),
        .o_bmc_spi_csn              ( SPI_OPFR_BMC_CS0_LVC3_N              ),
        .o_pch_spi_csn              ( {SPI_OPFR_CPU0_CS1_LVC18_N, SPI_OPFR_CPU0_CS0_LVC18_N}             ), 
        .o_cpu1_spi_csn             ( {SPI_CPU1_PFR_CTRL_CS1_N, SPI_CPU1_PFR_CTRL_CS_N}                ), 
        .o_pfr_spi_csn              ( SPI_PFR_CS0_N                         ), 
        .i_pfr_bmc_master_sel       ( spi_control_pfr_bmc_master_sel        ),
        .i_pfr_pch_master_sel       ( spi_control_pfr_pch_master_sel        ),
        .i_pfr_cpu1_master_sel      ( spi_control_pfr_cpu1_master_sel        ),
        .i_spi_master_bmc_pchn      ( spi_control_spi_master_bmc_pchn       ),
        .i_spi_master_path_sel      ( spi_control_spi_master_path_sel       ),
        .i_bmc_filter_disable       ( spi_control_bmc_filter_disable        ),
        .i_pch_filter_disable       ( spi_control_pch_filter_disable        ),
        .i_cpu1_filter_disable      ( spi_control_cpu1_filter_disable        ),
        .o_bmc_ibb_access_detected  ( spi_control_bmc_ibb_access_detected   ),
        .i_bmc_clear_ibb_detected   ( spi_control_bmc_clear_ibb_detected    ),
        .i_bmc_addr_mode_set_3b     ( spi_control_bmc_addr_mode_set_3b      ),
        .o_bmc_filtered_command_info( bmc_spi_filtered_command_info         ),
        .o_cpu0_flash0_filtered_command_info( cpu0_flash0_spi_filtered_command_info         ),
		.o_cpu0_flash1_filtered_command_info( cpu0_flash1_spi_filtered_command_info         ),
        .o_cpu1_filtered_command_info( cpu1_spi_filtered_command_info         ),
        .i_avmm_bmc_we_write        ( spi_filter_bmc_we_avmm_write          ),
        .i_avmm_bmc_we_address      ( spi_filter_bmc_we_avmm_address[platform_defs_pkg::BMC_WE_AVMM_ADDRESS_BITS-1+SPI_FILTER_AVMM_CSR_WIDTH:0]   ),
        .i_avmm_bmc_we_writedata    ( spi_filter_bmc_we_avmm_writedata      ),
        .i_avmm_bmc_we_read         ( spi_filter_bmc_we_avmm_read           ),
        .i_avmm_bmc_we_readdata     ( spi_filter_bmc_we_avmm_readdata       ),
        .i_avmm_bmc_we_readdatavalid( spi_filter_bmc_we_avmm_readdatavalid  ),
        .i_avmm_cpu0_flash0_we_write        ( spi_filter_cpu0_flash0_we_avmm_write          ),
        .i_avmm_cpu0_flash0_we_address      ( spi_filter_cpu0_flash0_we_avmm_address[platform_defs_pkg::PCH_WE_AVMM_ADDRESS_BITS-1+SPI_FILTER_AVMM_CSR_WIDTH:0]   ),
        .i_avmm_cpu0_flash0_we_writedata    ( spi_filter_cpu0_flash0_we_avmm_writedata      ),
        .i_avmm_cpu0_flash0_we_read         ( spi_filter_cpu0_flash0_we_avmm_read           ),
        .i_avmm_cpu0_flash0_we_readdata     ( spi_filter_cpu0_flash0_we_avmm_readdata       ),
        .i_avmm_cpu0_flash0_we_readdatavalid( spi_filter_cpu0_flash0_we_avmm_readdatavalid  ),
		.i_avmm_cpu0_flash1_we_write        ( spi_filter_cpu0_flash1_we_avmm_write          ),
        .i_avmm_cpu0_flash1_we_address      ( spi_filter_cpu0_flash1_we_avmm_address[platform_defs_pkg::PCH_WE_AVMM_ADDRESS_BITS-1+SPI_FILTER_AVMM_CSR_WIDTH:0]   ),
        .i_avmm_cpu0_flash1_we_writedata    ( spi_filter_cpu0_flash1_we_avmm_writedata      ),
        .i_avmm_cpu0_flash1_we_read         ( spi_filter_cpu0_flash1_we_avmm_read           ),
        .i_avmm_cpu0_flash1_we_readdata     ( spi_filter_cpu0_flash1_we_avmm_readdata       ),
        .i_avmm_cpu0_flash1_we_readdatavalid( spi_filter_cpu0_flash1_we_avmm_readdatavalid  ),
        .i_avmm_cpu1_flash0_we_write        ( spi_filter_cpu1_flash0_we_avmm_write          ),
        .i_avmm_cpu1_flash0_we_address      ( spi_filter_cpu1_flash0_we_avmm_address[platform_defs_pkg::CPU1_WE_AVMM_ADDRESS_BITS-1+SPI_FILTER_AVMM_CSR_WIDTH:0]   ),
        .i_avmm_cpu1_flash0_we_writedata    ( spi_filter_cpu1_flash0_we_avmm_writedata      ),
        .i_avmm_cpu1_flash0_we_read         ( spi_filter_cpu1_flash0_we_avmm_read           ),
        .i_avmm_cpu1_flash0_we_readdata     ( spi_filter_cpu1_flash0_we_avmm_readdata       ),
        .i_avmm_cpu1_flash0_we_readdatavalid( spi_filter_cpu1_flash0_we_avmm_readdatavalid  ),
		.i_avmm_cpu1_flash1_we_write        ( spi_filter_cpu1_flash1_we_avmm_write          ),
        .i_avmm_cpu1_flash1_we_address      ( spi_filter_cpu1_flash1_we_avmm_address[platform_defs_pkg::CPU1_WE_AVMM_ADDRESS_BITS-1+SPI_FILTER_AVMM_CSR_WIDTH:0]   ),
        .i_avmm_cpu1_flash1_we_writedata    ( spi_filter_cpu1_flash1_we_avmm_writedata      ),
        .i_avmm_cpu1_flash1_we_read         ( spi_filter_cpu1_flash1_we_avmm_read           ),
        .i_avmm_cpu1_flash1_we_readdata     ( spi_filter_cpu1_flash1_we_avmm_readdata       ),
        .i_avmm_cpu1_flash1_we_readdatavalid( spi_filter_cpu1_flash1_we_avmm_readdatavalid  ),
        .i_avmm_csr_address         ( spi_master_csr_avmm_address           ),
        .i_avmm_csr_read            ( spi_master_csr_avmm_read              ),
        .i_avmm_csr_write           ( spi_master_csr_avmm_write             ),
        .o_avmm_csr_waitrequest     ( spi_master_csr_avmm_waitrequest       ),
        .i_avmm_csr_writedata       ( spi_master_csr_avmm_writedata         ),
        .o_avmm_csr_readdata        ( spi_master_csr_avmm_readdata          ),
        .o_avmm_csr_readdatavalid   ( spi_master_csr_avmm_readdatavalid     ),
        .i_avmm_mem_address         ( spi_master_avmm_address               ),
        .i_avmm_mem_read            ( spi_master_avmm_read                  ),
        .i_avmm_mem_write           ( spi_master_avmm_write                 ),
        .o_avmm_mem_waitrequest     ( spi_master_avmm_waitrequest           ),
        .i_avmm_mem_writedata       ( spi_master_avmm_writedata             ),
        .o_avmm_mem_readdata        ( spi_master_avmm_readdata              ),
        .o_avmm_mem_readdatavalid   ( spi_master_avmm_readdatavalid         ),
        .i_dma_nios_master_sel      ( dma_nios_master_sel                   ),
        .i_dma_avmm_mem_address         ( dma_spi_avmm_mem_address          ),
        .i_dma_avmm_mem_read            ( dma_spi_avmm_mem_read             ),
        .i_dma_avmm_mem_write           ( 1'b0                              ),
        .i_dma_avmm_mem_burstcount      ( dma_spi_avmm_mem_burstcount       ),
        .o_dma_avmm_mem_waitrequest     ( dma_spi_avmm_mem_waitrequest      ),
        .i_dma_avmm_mem_writedata       ( 32'b0                             ),
        .o_dma_avmm_mem_readdata        ( dma_spi_avmm_mem_readdata         ),
        .o_dma_avmm_mem_readdatavalid   ( dma_spi_avmm_mem_readdatavalid    )

    );

    // implement tri-state drivers and input connections for SPI master data pins
    assign bmc_spi_master_data_in       = {SPI_OPFR_BMC_IO3_LVC3_R, SPI_OPFR_BMC_IO2_LVC3_R, SPI_OPFR_BMC_IO1_LVC3_R, SPI_OPFR_BMC_IO0_LVC3_R};
    assign SPI_OPFR_BMC_IO3_LVC3_R       = bmc_spi_master_data_oe[3] ? bmc_spi_master_data_out[3] : 1'bz;
    assign SPI_OPFR_BMC_IO2_LVC3_R       = bmc_spi_master_data_oe[2] ? bmc_spi_master_data_out[2] : 1'bz;
    assign SPI_OPFR_BMC_IO1_LVC3_R   = bmc_spi_master_data_oe[1] ? bmc_spi_master_data_out[1] : 1'bz;
    assign SPI_OPFR_BMC_IO0_LVC3_R   = bmc_spi_master_data_oe[0] ? bmc_spi_master_data_out[0] : 1'bz;
    
    assign pch_spi_master_data_in       = {SPI_OPFR_CPU0_IO3_LVC18_R, SPI_OPFR_CPU0_IO2_LVC18_R, SPI_OPFR_CPU0_IO1_LVC18_R, SPI_OPFR_CPU0_IO0_LVC18_R};
    assign SPI_OPFR_CPU0_IO3_LVC18_R            = pch_spi_master_data_oe[3] ? pch_spi_master_data_out[3] : 1'bz;
    assign SPI_OPFR_CPU0_IO2_LVC18_R            = pch_spi_master_data_oe[2] ? pch_spi_master_data_out[2] : 1'bz;
    assign SPI_OPFR_CPU0_IO1_LVC18_R            = pch_spi_master_data_oe[1] ? pch_spi_master_data_out[1] : 1'bz;
    assign SPI_OPFR_CPU0_IO0_LVC18_R            = pch_spi_master_data_oe[0] ? pch_spi_master_data_out[0] : 1'bz;
    
    assign cpu1_spi_master_data_in      = {SPI_CPU1_PFR_CTRL_IO3, SPI_CPU1_PFR_CTRL_IO2, SPI_CPU1_PFR_CTRL_MISO, SPI_CPU1_PFR_CTRL_MOSI};
    assign SPI_CPU1_PFR_CTRL_IO3        = cpu1_spi_master_data_oe[3] ? cpu1_spi_master_data_out[3] : 1'bz;
    assign SPI_CPU1_PFR_CTRL_IO2        = cpu1_spi_master_data_oe[2] ? cpu1_spi_master_data_out[2] : 1'bz;
    assign SPI_CPU1_PFR_CTRL_MISO       = cpu1_spi_master_data_oe[1] ? cpu1_spi_master_data_out[1] : 1'bz;
    assign SPI_CPU1_PFR_CTRL_MOSI       = cpu1_spi_master_data_oe[0] ? cpu1_spi_master_data_out[0] : 1'bz;
    
    assign pfr_spi_master_data_in       = {SPI_PFR_IO3, SPI_PFR_IO2, SPI_PFR_IO1, SPI_PFR_IO0};
    assign SPI_PFR_IO3                  = pfr_spi_master_data_oe[3] ? pfr_spi_master_data_out[3] : 1'bz;
    assign SPI_PFR_IO2                  = pfr_spi_master_data_oe[2] ? pfr_spi_master_data_out[2] : 1'bz;
    assign SPI_PFR_IO1                  = pfr_spi_master_data_oe[1] ? pfr_spi_master_data_out[1] : 1'bz;
    assign SPI_PFR_IO0                  = pfr_spi_master_data_oe[0] ? pfr_spi_master_data_out[0] : 1'bz;
    
    // FM_PFR_CPU0_SPI_MASTERSEL: 0 -> CPU, 1 -> CPLD
    // ---------------------------------------------------------------------------------------------------------
    // PWRGD_AUX_PWRGD_PFR_CPU0 | FM_PFR_CPU0_SPI_MASTERSEL |   Descption
    // ---------------------------------------------------------------------------------------------------------
    // 0                      |    0               |   Platform reset, let firmware control
    // 0                      |    1               |   CPLD goes to CPU tmins 1 flow, let firmware control
    // 1                      |    0               |   CPU is up, let firmware control
    // 1                      |    1               |   Seamless update, hold it asserted if pltrst happen
    assign RST_PLTRST_CPU0_PFR_LVC3_N = (PWRGD_AUX_PWRGD_PFR_CPU0 & FM_PFR_CPU0_SPI_MASTERSEL & hold_pltrst_in_seamless) ? 1'b0: RST_PLTRST_CPU0_N;

    assign gpi_1[gen_gpi_signals_pkg::GPI_1_GPO_2_RST_PLTRST_CPU0_N_BIT_POS] = gpo_2[gen_gpo_controls_pkg::GPO_2_RST_PLTRST_CPU0_N_BIT_POS];
    
    assign PWRGD_AUX_PWRGD_PFR_CPU1 = PWRGD_AUX_PWRGD_CPU1;
    assign RST_PLTRST_CPU1_PFR_LVC3_N = RST_PLTRST_CPU1_N;

    //#########################################################################
    // SMBus Relays
    //#########################################################################

    // logic to implement the open-drain pins for scl/sda on the slave and master busses
    logic smbus_relay1_master_scl_in;
    logic smbus_relay1_master_scl_oe;
    logic smbus_relay1_master_sda_in;
    logic smbus_relay1_master_sda_oe;
    logic smbus_relay1_slave_scl_in;
    logic smbus_relay1_slave_scl_oe;
    logic smbus_relay1_slave_sda_in;
    logic smbus_relay1_slave_sda_oe;
    assign smbus_relay1_master_scl_in = SMB_PMBUS1_BMC_LVC3_SCL;
    assign smbus_relay1_master_sda_in = SMB_PMBUS1_BMC_LVC3_SDA;
    assign smbus_relay1_slave_scl_in  = SMB_PMBUS1_SCM_SCL_R;
    assign smbus_relay1_slave_sda_in  = SMB_PMBUS1_SCM_SDA_R;
    // this is to keep the bus busy so that host will not transmit transaction when RFNVRAM master is accessing the bus
    assign SMB_PMBUS1_BMC_LVC3_SCL = ((rfnvram_scl_oe && (slave_portid == 3'b100)) || smbus_relay1_master_scl_oe) ? 1'b0 : 1'bz;
    assign SMB_PMBUS1_BMC_LVC3_SDA = ((rfnvram_sda_oe && (slave_portid == 3'b100)) || smbus_relay1_master_sda_oe) ? 1'b0 : 1'bz;
    assign SMB_PMBUS1_SCM_SCL_R   = smbus_relay1_slave_scl_oe ? 1'b0 : 1'bz;
    assign SMB_PMBUS1_SCM_SDA_R   = smbus_relay1_slave_sda_oe ? 1'b0 : 1'bz;
    
    // Instantiate the relay block with no address or command filtering enabled
    smbus_filtered_relay #(
        .FILTER_ENABLE              ( 1                                                 ),      // enable command filtering
        .CLOCK_PERIOD_PS            ( platform_defs_pkg::SYS_CLOCK_PERIOD_PS            ),
        .BUS_SPEED_KHZ              ( platform_defs_pkg::RELAY1_BUS_SPEED_KHZ           ),
        .NUM_RELAY_ADDRESSES        ( gen_smbus_relay_config_pkg::RELAY1_NUM_ADDRESSES  ),
        .SMBUS_RELAY_ADDRESS        ( gen_smbus_relay_config_pkg::RELAY1_I2C_ADDRESSES  ),
        .SCL_LOW_TIMEOUT_PERIOD_MS  ( platform_defs_pkg::SCL_LOW_TIMEOUT_PERIOD_MS      ),
        .MCTP_OUT_OF_BAND_ENABLE    ( 0                                                 )       //mctp out of band feature turned off by default
    ) u_smbus_filtered_relay_1 (
        .clock                 ( sys_clk                       ),
        .i_resetn              ( sys_clk_reset_sync_n          ),
        .i_block_disable       ( relay1_block_disable          ),
        .i_filter_disable      ( relay1_filter_disable         ),
        .i_relay_all_addresses ( relay1_all_addresses          ),
        .ia_master_scl         ( smbus_relay1_master_scl_in    ),
        .o_master_scl_oe       ( smbus_relay1_master_scl_oe    ),
        .ia_master_sda         ( smbus_relay1_master_sda_in    ),
        .o_master_sda_oe       ( smbus_relay1_master_sda_oe    ),
        .ia_slave_scl          ( smbus_relay1_slave_scl_in     ),
        .o_slave_scl_oe        ( smbus_relay1_slave_scl_oe     ),
        .ia_slave_sda          ( smbus_relay1_slave_sda_in     ),
        .o_slave_sda_oe        ( smbus_relay1_slave_sda_oe     ),
        .i_avmm_write          ( relay1_avmm_write             ),
        .i_avmm_address        ( relay1_avmm_address           ),
        .i_avmm_writedata      ( relay1_avmm_writedata         )
    );

    // logic to implement the open-drain pins for scl/sda on the slave and master busses
    logic smbus_relay2_master_scl_in;
    logic smbus_relay2_master_scl_oe;
    logic smbus_relay2_master_sda_in;
    logic smbus_relay2_master_sda_oe;
    logic smbus_relay2_slave_scl_in;
    logic smbus_relay2_slave_scl_oe;
    logic smbus_relay2_slave_sda_in;
    logic smbus_relay2_slave_sda_oe;
    assign smbus_relay2_master_scl_in = SMB_PMBUS2_BMC_LVC3_SCL;
    assign smbus_relay2_master_sda_in = SMB_PMBUS2_BMC_LVC3_SDA;
    assign smbus_relay2_slave_scl_in  = SMB_PMBUS2_SCM_SCL_R;
    assign smbus_relay2_slave_sda_in  = SMB_PMBUS2_SCM_SDA_R;
    assign SMB_PMBUS2_BMC_LVC3_SCL = ((rfnvram_scl_oe && (slave_portid == 3'b101)) || smbus_relay2_master_scl_oe) ? 1'b0 : 1'bz;
    assign SMB_PMBUS2_BMC_LVC3_SDA = ((rfnvram_sda_oe && (slave_portid == 3'b101)) || smbus_relay2_master_sda_oe) ? 1'b0 : 1'bz;  // common core SMBus register file needs to be able to drive this open-drain signal as well
    assign SMB_PMBUS2_SCM_SCL_R = smbus_relay2_slave_scl_oe ? 1'b0 : 1'bz;
    assign SMB_PMBUS2_SCM_SDA_R = smbus_relay2_slave_sda_oe ? 1'b0 : 1'bz;
    
    // Instantiate the relay block with no address or command filtering enabled
    smbus_filtered_relay #(
        .FILTER_ENABLE              ( 1                                                 ),      // enable command filtering
        .CLOCK_PERIOD_PS            ( platform_defs_pkg::SYS_CLOCK_PERIOD_PS            ),
        .BUS_SPEED_KHZ              ( platform_defs_pkg::RELAY2_BUS_SPEED_KHZ           ),
        .NUM_RELAY_ADDRESSES        ( gen_smbus_relay_config_pkg::RELAY2_NUM_ADDRESSES  ),
        .SMBUS_RELAY_ADDRESS        ( gen_smbus_relay_config_pkg::RELAY2_I2C_ADDRESSES  ),
        .SCL_LOW_TIMEOUT_PERIOD_MS  ( platform_defs_pkg::SCL_LOW_TIMEOUT_PERIOD_MS      ),
        .MCTP_OUT_OF_BAND_ENABLE    ( 0                                                 )       //mctp out of band feature turned off by default
    ) u_smbus_filtered_relay_2 (
        .clock                 ( sys_clk                       ),
        .i_resetn              ( sys_clk_reset_sync_n          ),
        .i_block_disable       ( relay2_block_disable          ),
        .i_filter_disable      ( relay2_filter_disable         ),
        .i_relay_all_addresses ( relay2_all_addresses          ),
        .ia_master_scl         ( smbus_relay2_master_scl_in    ),
        .o_master_scl_oe       ( smbus_relay2_master_scl_oe    ),
        .ia_master_sda         ( smbus_relay2_master_sda_in    ),
        .o_master_sda_oe       ( smbus_relay2_master_sda_oe    ),
        .ia_slave_scl          ( smbus_relay2_slave_scl_in     ),
        .o_slave_scl_oe        ( smbus_relay2_slave_scl_oe     ),
        .ia_slave_sda          ( smbus_relay2_slave_sda_in     ),
        .o_slave_sda_oe        ( smbus_relay2_slave_sda_oe     ),
        .i_avmm_write          ( relay2_avmm_write             ),
        .i_avmm_address        ( relay2_avmm_address           ),
        .i_avmm_writedata      ( relay2_avmm_writedata         )
    );

    // logic to implement the open-drain pins for scl/sda on the slave and master busses
    logic smbus_relay3_master_scl_in;
    logic smbus_relay3_master_scl_oe;
    logic smbus_relay3_master_sda_in;
    logic smbus_relay3_master_sda_oe;
    logic smbus_relay3_slave_scl_in;
    logic smbus_relay3_slave_scl_oe;
    logic smbus_relay3_slave_sda_in;
    logic smbus_relay3_slave_sda_oe;
    assign smbus_relay3_master_scl_in = SMB_HSBP_BMC_SCL_LVC3;
    assign smbus_relay3_master_sda_in = SMB_HSBP_BMC_SDA_LVC3;
    assign smbus_relay3_slave_scl_in  = SMB_HSBP_SCM_SCL_LVC3_R1;
    assign smbus_relay3_slave_sda_in  = SMB_HSBP_SCM_SDA_LVC3_R1;
    assign SMB_HSBP_BMC_SCL_LVC3 = ((rfnvram_scl_oe && (slave_portid == 3'b110)) || smbus_relay3_master_scl_oe) ? 1'b0 : 1'bz;
    assign SMB_HSBP_BMC_SDA_LVC3 = ((rfnvram_sda_oe && (slave_portid == 3'b110)) || smbus_relay3_master_sda_oe) ? 1'b0 : 1'bz;
    assign SMB_HSBP_SCM_SCL_LVC3_R1 = smbus_relay3_slave_scl_oe ? 1'b0 : 1'bz;
    assign SMB_HSBP_SCM_SDA_LVC3_R1   = smbus_relay3_slave_sda_oe ? 1'b0 : 1'bz;
    
    // Instantiate the relay block with no address or command filtering enabled
    smbus_filtered_relay #(
        .FILTER_ENABLE              ( 1                                                 ),      // enable command filtering
        .CLOCK_PERIOD_PS            ( platform_defs_pkg::SYS_CLOCK_PERIOD_PS            ),
        .BUS_SPEED_KHZ              ( platform_defs_pkg::RELAY3_BUS_SPEED_KHZ           ),
        .NUM_RELAY_ADDRESSES        ( gen_smbus_relay_config_pkg::RELAY3_NUM_ADDRESSES  ),
        .SMBUS_RELAY_ADDRESS        ( gen_smbus_relay_config_pkg::RELAY3_I2C_ADDRESSES  ),
        .SCL_LOW_TIMEOUT_PERIOD_MS  ( platform_defs_pkg::SCL_LOW_TIMEOUT_PERIOD_MS      ),
        .MCTP_OUT_OF_BAND_ENABLE    ( 1                                                 )       //mctp out of band feature turned on for BMC relay only
    ) u_smbus_filtered_relay_3 (
        .clock                 ( sys_clk                       ),
        .i_resetn              ( sys_clk_reset_sync_n          ),
        .i_block_disable       ( relay3_block_disable          ),
        .i_filter_disable      ( relay3_filter_disable         ),
        .i_relay_all_addresses ( relay3_all_addresses          ),
        .ia_master_scl         ( smbus_relay3_master_scl_in    ),
        .o_master_scl_oe       ( smbus_relay3_master_scl_oe    ),
        .ia_master_sda         ( smbus_relay3_master_sda_in    ),
        .o_master_sda_oe       ( smbus_relay3_master_sda_oe    ),
        .ia_slave_scl          ( smbus_relay3_slave_scl_in     ),
        .o_slave_scl_oe        ( smbus_relay3_slave_scl_oe     ),
        .ia_slave_sda          ( smbus_relay3_slave_sda_in     ),
        .o_slave_sda_oe        ( smbus_relay3_slave_sda_oe     ),
        .i_avmm_write          ( relay3_avmm_write             ),
        .i_avmm_address        ( relay3_avmm_address           ),
        .i_avmm_writedata      ( relay3_avmm_writedata         )
    );


    i3c_host #(
        .PEC_ENABLE_PARAM (platform_defs_pkg::I3C_PEC_ENABLE)   
    ) u_i3c_host (
        .clk_100m           (clk100M),
        .clk_100m_reset_n   (clk100M_reset_sync_n),
        .clk_i3c            (i3c_avmm_clk),
        .clk_i3c_reset_n    (~i3c_avmm_areset),
        .reset_n            (1'b1),
        .avm_read           (i3c_avmm_read),
        .avm_readdata       (i3c_avmm_readdata),
        .avm_readdatavalid  (i3c_avmm_readdatavalid),
        .avm_write          (i3c_avmm_write),
        .avm_writedata      (i3c_avmm_writedata),
        .avm_address        (i3c_avmm_address),
        .avm_waitrequest    (i3c_avmm_waitrequest),
        .pur_oe             (i3c_pur_oe),
        .scl_data_in        (i3c_scl_data_in),    
        .scl_data_out       (i3c_scl_data_out),     
        .scl_oe             (i3c_scl_oe),
        .sda_data_in        (i3c_sda_data_in),    
        .sda_data_out       (i3c_sda_data_out),     
        .sda_oe             (i3c_sda_oe),
        .i3c_core_clk       (i3c_core_clk),
        .i3c_core_reset_n   (i3c_core_reset_n)

    );

    aes256_gcm u_aes256_gcm (
        .clk              (aes256_gcm_avmm_clk),
        .reset_n          (aes256_gcm_avmm_areset),
        .avm_write        (aes256_gcm_avmm_write),
        .avm_writedata    (aes256_gcm_avmm_writedata),
        .avm_address      (aes256_gcm_avmm_address),
        .avm_waitrequest  (aes256_gcm_avmm_waitrequest),
        .avm_read         (aes256_gcm_avmm_read),
        .avm_readdata     (aes256_gcm_avmm_readdata),
        .avm_readdatavalid(aes256_gcm_avmm_readdatavalid)
    );

    assign i3c_scl_data_in = i3c_mng_switch_sel_gpo_out ? I3C_PFR_MNG_SCL : I3C_PFR_BMC_SCL;
    assign i3c_sda_data_in = i3c_mng_switch_sel_gpo_out ? I3C_PFR_MNG_SDA : I3C_PFR_BMC_SDA;

    assign I3C_PFR_MNG_SCL = i3c_mng_switch_sel_gpo_out ? (i3c_scl_oe ? i3c_scl_data_out : 1'bz) : 1'bz;
    assign I3C_PFR_MNG_SDA = i3c_mng_switch_sel_gpo_out ? (i3c_sda_oe ? i3c_sda_data_out : 1'bz) : 1'bz;
    assign FM_I3C_PFR_MNG_PUR_EN = i3c_mng_switch_sel_gpo_out ? i3c_pur_oe : 1'b0; 
    
    assign I3C_PFR_BMC_SCL = i3c_mng_switch_sel_gpo_out ? 1'bz : (i3c_scl_oe ? i3c_scl_data_out : 1'bz);
    assign I3C_PFR_BMC_SDA = i3c_mng_switch_sel_gpo_out ? 1'bz : (i3c_sda_oe ? i3c_sda_data_out : 1'bz);
    assign FM_I3C_PFR_BMC_PUR_EN = i3c_mng_switch_sel_gpo_out ? 1'b0 : i3c_pur_oe; 


    // SGPIO master core
    master_ngsx #(
        .BYTE_REGS  (2)
    ) u_master (
        .iRst_n     (clk2M_reset_sync_n),
        .iClk       (clk2M),
        .oLoad_n    (SGPIO_PFR_LD_N),
        .iPData     ({7'h0, SCM_CPLD_UPDATE_HIDE, global_state[7:0]}),
        .oSData     (SGPIO_PFR_DOUT),
        .iSData     (SGPIO_PFR_DIN),
        .oClk       (SGPIO_PFR_CLK),
		.oPData     ({oPData_reserved, FM_CPU1_SKTOCC_LVT3_N, FM_CPU0_SKTOCC_LVT3_N, PWRGD_CPU0_LVC3, RSU_IP_HIDE_DONE, SCM_BOARD_ID_0, SCM_BOARD_ID_1, SCM_BOARD_ID_2, SCM_BOARD_ID_3, SCM_BOARD_ID_4, SCM_BOARD_ID_5})	//Only using last 10 bits of incoming SGPIO info

    );
	
	wire clamp_io;
	wire io_clamped;
	assign clamp_io = gpo_2[gen_gpo_controls_pkg::GPO_2_CLAMP_IO_BIT_POS];
	assign gpi_1[gen_gpi_signals_pkg::GPI_1_IO_CLAMPED_BIT_POS] = io_clamped;

	jtag_lock_controller u_jtag (
		.clk_in			(clk2M),
		.resetn			(clk2M_reset_sync_n),
		.lock_unlock_n	(1'b1),
		.clamp_io		(clamp_io),
		.io_clamped		(io_clamped),
		.tck_external	(tck_external),
		.tdi_external	(tdi_external),
		.tms_external	(tms_external),
		.tdo_external	(tdo_external)
	);
	

endmodule
    
